/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tpgen.manchester.w3org;

import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author shanki
 */
public class ForbiddenConstructs {
    private static final Construct[] some  = new Construct[] {
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList
    };
    
    private static final Construct[] only   = new Construct[] {
        Construct.restrictionObjectOnly,
        Construct.restrictionDataOnly,
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.restrictionObjectExactly,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList  
    };
    
    private static final Construct[] value   = new Construct[] {
        Construct.restrictionObjectValue,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList       
    };
    
    private static final Construct[] min   = new Construct[] {
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList
    };
    
    private static final Construct[] exactly   = new Construct[] {
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList     
    };
    
    private static final Construct[] max   = new Construct[] {
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.factNot,
        Construct.primaryNot,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList
    };
    
    private static final Construct[] not   = new Construct[] {
        Construct.factNot,
        Construct.primaryNot,
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectOnly,
        Construct.restrictionDataOnly,
        Construct.restrictionObjectValue,
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.descriptionOr,
        Construct.conjunctionAnd,
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList      
    };    

    private static final Construct[] oneOf   = new Construct[] {
        Construct.dataAtomicLiteralList,
        Construct.atomicIndividualList,
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectOnly,
        Construct.restrictionDataOnly,
        Construct.restrictionObjectValue,
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.conjunctionAnd,
        Construct.factNot,
        Construct.primaryNot,   
    };
    
    private static final Construct[] classUnion   = new Construct[] {
        Construct.descriptionOr,
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectOnly,
        Construct.restrictionDataOnly,
        Construct.restrictionObjectValue,
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.conjunctionAnd,
        Construct.factNot,
        Construct.primaryNot,
    };
    
    private static final Construct[] classIntersection   = new Construct[] {
        Construct.conjunctionAnd,
        Construct.restrictionObjectSome,
        Construct.restrictionDataSome,
        Construct.restrictionObjectOnly,
        Construct.restrictionDataOnly,
        Construct.restrictionObjectValue,
        Construct.restrictionObjectMin,
        Construct.restrictionDataMin,
        Construct.restrictionObjectExactly,
        Construct.restrictionDataExactly,
        Construct.restrictionObjectMax,
        Construct.restrictionDataMax,
        Construct.descriptionOr,
        Construct.factNot,
        Construct.primaryNot,
    };  
    
    private static final Map<Construct, Construct[]> forbidden;


    
    static {
        forbidden   = new EnumMap<Construct, Construct[]>(Construct.class);
        forbidden.put(Construct.restrictionObjectSome, some);
        forbidden.put(Construct.restrictionDataSome, some);
        forbidden.put(Construct.restrictionObjectMax, max);
        forbidden.put(Construct.restrictionDataMax, max);
        forbidden.put(Construct.restrictionObjectMin, min);
        forbidden.put(Construct.restrictionDataMin, min);
        forbidden.put(Construct.restrictionObjectExactly, exactly);
        forbidden.put(Construct.restrictionDataExactly, exactly);
        forbidden.put(Construct.factNot, not);
        forbidden.put(Construct.primaryNot, not);
        forbidden.put(Construct.descriptionOr, classUnion);
        forbidden.put(Construct.conjunctionAnd, classIntersection);
        forbidden.put(Construct.atomicIndividualList, oneOf);
        forbidden.put(Construct.dataAtomicLiteralList, oneOf);
        forbidden.put(Construct.restrictionObjectOnly, only);
        forbidden.put(Construct.restrictionDataOnly, only);
        forbidden.put(Construct.restrictionObjectValue, value);
    }
    
    public static Set<Construct> expand(Iterable<Construct> forbiddenConstructs) {
        Set<Construct> all    = new HashSet<Construct>();
        
        for (Construct construct : forbiddenConstructs) {
            all.addAll(expand(construct));
        }
        
        return all;
    }
    
    public static Collection<? extends Construct> expand(Construct construct) {
        Set<Construct> all    = new HashSet<Construct>();
        all.add(construct);
        
        if (forbidden.containsKey(construct)) {        
            all.addAll(Arrays.asList(forbidden.get(construct)));
        }
        
        return all;
    }    
}
